package com.sgzn.sgpay.web.aop;

import com.alibaba.fastjson.JSON;
import com.sgzn.sgpay.enums.AppName;
import com.sgzn.sgpay.enums.SgsResponseCode;
import com.sgzn.sgpay.exception.SgpayException;
import com.sgzn.sgpay.exception.ValidateException;
import com.sgzn.sgpay.model.response.SgsResultResponse;
import com.sgzn.sgpay.util.SerialNoUtil;
import com.sgzn.sgpay.util.ValidateUtil;
import com.sgzn.sgpay.web.request.Request;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 接口服务类AOP
 * @author zhongzhongyong
 * @version Id: WebAop.java, v 0.1 2018/4/3 15:21 zhongzhongyong Exp $$
 */
@Aspect
@Service
@Slf4j
public class WebAop {

    @Resource
    private ValidateUtil validateUtil;

    @Pointcut("execution(public * com.sgzn.sgpay.web.controller..*.*(..)) && args(request,..)")
    private void servicePointcut(Request request) {
        //do nothing here
    }

    @Around("servicePointcut(request)")
    public Object aroundMethod(ProceedingJoinPoint jp, Request request) throws Throwable {
        long startMillis = System.currentTimeMillis();
        String initiationID = SerialNoUtil.generateSerialNo(AppName.SGW);
        MDC.put("initiationID", initiationID);

        String className = jp.getTarget().getClass().getSimpleName();
        String methodName = jp.getSignature().getName();

        //填充非业务参数
        request.setInitiationID(initiationID);

        Object[] args = jp.getArgs();

        Object response = null;
        String succFlag = "Success";
        try {
            // 1. 校验参数
            for(int i=0, length = args.length; i<length; i++){
                if (args[i] == null){
                    throw new IllegalArgumentException("Request must be not null");
                } else {
                    validateUtil.validate(args[i]);
                }
            }
            log.info("call[{}][{}]PARAMETER:[{}]", className, methodName, args);
            response = jp.proceed();
        }catch (ValidateException e) {
            succFlag = "Failure";
            log.error("Here throw an ValidateException:", e);
            response = getFailResponse(SgsResponseCode.C10001.getResponseCode(), e.getMessage());
        }catch (SgpayException e) {
            succFlag = "Failure";
            log.error("Here throw an SgpayException:{}", e.getMessage());
            response = getFailResponse(e.getCode(), e.getDesc());
        } catch (Exception e) {
            succFlag = "Failure";
            log.error("Here throw an Exception:", e);
            response = getFailResponse(SgsResponseCode.C503.getResponseCode(), SgsResponseCode.C503.getResponseDesc());
        }
        log.info("call[{}][{}][{}ms][{}]RESPONSE:Result[{}]", className, methodName, System.currentTimeMillis() - startMillis, succFlag, response);
        return response;
    }

    /**
     * 获取失败响应
     * @return
     */
    private String getFailResponse(String responseCode, String responseMsg) {
        SgsResultResponse<String> response = new SgsResultResponse<String>();
        response.setErrorCode(responseCode);
        response.setErrorMsg(responseMsg);
        response.setResult(null);
        return JSON.toJSONString(response);
    }
}
